图片即文件,在jsp中文件上传很简单,一个type为file的input,一个form指定enctype为multipart/form-data,通过post提交到后台利用apache的commons-fileupload.XXjar即可实现。EasyUI的filebox组件也是用来进行文件上传的,但我这里的业务需求不仅仅是图片上传,还有其他文本框的提交,所以需要文件上传后再点击保存。界面展示图片是在数据列表中,因此需要小图,点击图片后再展示大图。
因为这里支付截图上传后需跟另一个支付流水的文本框一起在form里提交,因此需要多加一个文件上传按钮来先进行图片的上传:
选好图片后点击图片上传:
传好后点击保存,支付流水和截图将一起入库。再看数据列表的展示:
鼠标点击小图展示大图:
这里上传和展示就一起说明了:
先看html,首先datagrid中我们设置列头时执行支付截图需要通过imgFormatter方法进行格式化:
支付流水支付截图
再看点击编辑时弹出的form:
支付信息
再看下js,展示图片、上传图片和保存信息都在这里:
var url; var uploadPath; $(function () { $('#photoUrl').filebox({ prompt: '请选择一张图片...', width: '280px', buttonText: '点击选择图片' }) $('#photoUrl').filebox({ onChange: function () { var fileObj = $("input[name='photoUrl']")[0]; var allowExtention = ".jpg,.bmp,.gif,.png,.jpeg"; var extention = fileObj.value.substring(fileObj.value.lastIndexOf(".") + 1).toLowerCase(); if (allowExtention.indexOf(extention) == -1) { $.messager.show({ // show error message title: '错误', msg: "只支持以下格式图片:" + allowExtention + "." }); $('#photoUrl').filebox('reset'); $('#photoUrl').filebox('setValue', ""); $('#photoUrl').filebox('disableValidation'); } } }) }); function imgFormatter(value, row, index) { if ('' != value && null != value) { var imgResult = ""; return imgResult; } } function download(img) { var imgTemp = "http://localhost:8888" + img; $('#dlgImg').dialog({ title: '展示全图', width: 600, height: 500, resizable: true, closed: false, cache: false, modal: true }); $('#imgTemp').attr("src", imgTemp); } function editFlow() { var row = $('#dg').datagrid('getSelected'); if (row) { $('#dlg').dialog('open').dialog('setTitle', '编辑'); $('#fm').form('load', row); url = 'update_pay?id=' + row.id; } } function saveFile() { // 异步提交文件 $.ajaxFileUpload({ url: 'uploadFile', secureuri: false, fileElementId: $("input[name='photoUrl']").attr("id"), type: 'post', success: function (data) { var reg = /(.+)<\/pre>/g; var temp = data.match(reg); temp = RegExp.$1; var data = eval('(' + temp + ')'); if (data.resultPath) { uploadPath = data.resultPath; $.messager.show({ // show error message title: '成功', msg: '图片上传成功.' }); } }, error: function () { $.messager.show({ // show error message title: '错误', msg: "图片上传失败." }); } }); $('#photoUrl').filebox('reset'); $('#photoUrl').filebox('setValue', ""); $('#photoUrl').filebox('disableValidation'); } function saveFlow() { if (uploadPath) { url = url + '&photoUrl=' + uploadPath; } $('#fm').form('submit', { url: url, onSubmit: function () { return $(this).form('validate'); }, success: function (result) { var result = eval('(' + result + ')'); if (result.errorMsg) { $.messager.show({ title: '错误', msg: "保存失败." }); } else { $('#dlg').dialog('close'); // close the dialog $('#dg').datagrid('reload'); // reload the user data } } }); }
头文件里引入ajaxfileupload.js
ajaxfileupload.js直接放在静态文件目录下即可,当然你也可以自己找地方,上面的引入路径能匹配到即可:
jQuery.extend({ createUploadIframe: function (d, b) { var a = "jUploadFrame" + d; var c = '
通过ajaxfileupload.js进行异步调用获取到的json响应会多一些文本(其实就是一个<pre>标签),所以上面在点击保存时saveFile()通过正则过滤才能真正拿到图片路径。
最后看下后台,文件上传Controller:
@ResponseBody @RequestMapping(value = "uploadFile", method = RequestMethod.POST) public Object uploadFile(@RequestParam(value = "photoUrl") MultipartFile file, HttpServletRequest request) { MapresultMap = new HashMap<>(); String error = null; // 获取文件名 String fileName = file.getOriginalFilename(); // 根据文件后缀生成新的文件名 String type = fileName.substring(fileName.lastIndexOf(".") + 1); String newFileName = Utils.createFileName(type); fileName = newFileName != null ? newFileName : fileName; // 上传文件并返回相对路径 String resultPath = null; try { resultPath = flowService.uploadFile(file.getBytes(), filePath, fileName); } catch (Exception e) { LOGGER.error("--uploadFile-- error: {}", e); error = e.getMessage(); } if (error != null) { resultMap.put("errorMsg", error); } else { resultMap.put("resultPath", resultPath); } return resultMap; }
这里MultipartFile是spring自带的,在spring boot中我们无需引入额外的jar包,看下导入的包路径即可明了:
org.springframework.web.multipart.MultipartFile
再看调用的service:
/** * 上传文件 * * @param file * @param filePath * @param fileName * @return * @throws Exception */ public String uploadFile(byte[] file, String filePath, String fileName) throws Exception { // 判断文件目录是否存在,不存在则新建 File targetFile = new File(filePath); if (!targetFile.exists()) { targetFile.mkdir(); } // 新文件路径 String fullPath = filePath + "/" + fileName; FileOutputStream out = new FileOutputStream(fullPath); out.write(file); out.flush(); out.close(); // 入库路径 return fullPath.substring(fullPath.indexOf("/")); }
上传是不是很简单?但有两点需要注意:一个是文件上传大小限制,一个是文件存储目录必须要跟js中的展示url建立映射,这两点都需要在application.properties中配置:
#图片保存路径imgUpload.file.savePath=D:/imgUpload#上传文件大小设置10M,默认是1Mspring.servlet.multipart.maxFileSize=10485760
文件路径在上面的Controller里通过定义全局变量filePath,而filePath则是通过注解从application.properties获取
@Value("${ imgUpload.file.savePath}")private String filePath;
通过新增java配置来映射物理文件地址和web访问url:
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class WebConfigurer implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/imgUpload/**").addResourceLocations("file:D:/imgUpload/"); }}
我将存放在D盘的imgUpload映射给tomcat下webapps的/imgUpload,这样在dataGrid中展示的/imgUpload/test.jpg(后台入库时存储的图片路径)就能通过本机地址http://localhost:8888/imgUpload/test.jpg访问到并展示出来了。